﻿using System;
using System.Web.Mvc;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Rally_MvvmC.Library
{
    public static class ViewModelSessionState
    {
        public static type FromSessionState<type>(this ViewControllerBase viewControllerBase, string key)
        where type : class
        {
            type returnVal = null;

            if (viewControllerBase != null && viewControllerBase.Request.Cookies.AllKeys.Contains(key))
            {

                returnVal = SimpleStringCrypt.Decrypt(viewControllerBase.Request.Cookies[key].Value) as type;
            }

            return returnVal;
        }


        public static type FromSessionStateVal<type>(this ActionFilterAttribute viewControllerBase, ResultExecutingContext info, string key)
        where type : class
        {
            type returnVal = null;

            if (viewControllerBase != null && info.HttpContext.Request.Cookies.AllKeys.Contains(key))
            {

                returnVal = SimpleStringCrypt.Decrypt(info.HttpContext.Request.Cookies[key].Value) as type;
            }

            return returnVal;
        }


        public static type FromSessionStateVal<type>(this ViewControllerBase viewControllerBase, string key)
        where type : struct
        {
            object returnVal = null;
            if (!viewControllerBase.Request.Cookies.AllKeys.Contains(key))
            {
                var returnType = (new type()).GetType().Name;
                switch (returnType)
                {
                    case "Int32":
                        returnVal = 0;
                        break;
                    case "Int16":
                        returnVal = short.Parse("0");
                        break;
                    case "Boolean":
                        returnVal = false;
                        break;
                    default:
                        returnVal = 0;
                        break;
                }
            }
            else
            {
                var SessionStateReturnVal = SimpleStringCrypt.Decrypt(viewControllerBase.Request.Cookies[key].Value);
                if (SessionStateReturnVal == null)
                {
                    var returnType = (new type()).GetType().Name;
                    switch (returnType)
                    {
                        case "Int32":
                            returnVal = 0;
                            break;
                        case "Int16":
                            returnVal = short.Parse("0");
                            break;
                        case "Boolean":
                            returnVal = false;
                            break;
                        default:
                            returnVal = SessionStateReturnVal;
                            break;
                    }
                }
                else
                {
                    var returnType = (new type()).GetType().Name;
                    switch (returnType)
                    {
                        case "Int32":
                            returnVal = int.Parse(SessionStateReturnVal);
                            break;
                        case "Int16":
                            returnVal = short.Parse(SessionStateReturnVal);
                            break;
                        case "Boolean":
                            returnVal = bool.Parse(SessionStateReturnVal);
                            break;
                        default:
                            returnVal = SessionStateReturnVal;
                            break;
                    }
                }
            }

            return ((type)returnVal);
        }

        public static void ExpireSessionState(this ViewControllerBase viewControllerBase)
        {
            foreach (var cookieName in viewControllerBase.Request.Cookies.AllKeys)
            {
                var cookie = viewControllerBase.Request.Cookies[cookieName];
                if (cookie != null && cookie.Expires <= DateTime.Now)
                {
                    cookie.Expires = DateTime.Now.AddDays(-1);
                    viewControllerBase.Response.Cookies.Set(cookie);
                }
            }
        }

        public static void ToSessionState(this ViewControllerBase viewControllerBase, string key, object value, bool? remeberMe)
        {
            bool persistCookie = remeberMe.HasValue ? remeberMe.Value : viewControllerBase.FromSessionStateVal<bool>("RememberMe")  ;
            if (value == null)
            {
                if (viewControllerBase.Request.Cookies.AllKeys.Contains(key))
                {
                    var cookie = viewControllerBase.Request.Cookies[key];
                    cookie.Expires = DateTime.Now.AddDays(-1);
                    viewControllerBase.Response.Cookies.Set(cookie);
                }
                return;
            }
            else
            {
                var cookie = new System.Web.HttpCookie(key, SimpleStringCrypt.Crypt(value.ToString()));
                if (persistCookie)
                {
                    cookie.Expires = DateTime.Now.AddDays(+10);
                }
                else
                {
                }
                if (viewControllerBase.Request.Cookies.AllKeys.Contains(key))
                {
                    viewControllerBase.Response.Cookies.Set(cookie);
                }
                else
                {
                    viewControllerBase.Response.Cookies.Add(cookie);
                }
            }
        }

        public static type FromToSessionState<type>(this ViewControllerBase viewControllerBase, string key, Func<type> ToFunction)
        where type : class
        {
            var returnVal = FromSessionState<type>(viewControllerBase, key);

            if (returnVal == null)
            {
                returnVal = ToFunction.Invoke();
                ToSessionState(viewControllerBase, key, returnVal, null);
            }

            return returnVal as type;
        }

        public static type FromToSessionStateVal<type>(this ViewControllerBase viewControllerBase, string key, Func<type> ToFunction)
        where type : struct
        {
            var returnVal = FromSessionStateVal<type>(viewControllerBase, key);
            if ((returnVal is int && int.Parse(returnVal.ToString()) == 0))
            {
                returnVal = ToFunction.Invoke();
                var cookie = new System.Web.HttpCookie(key, SimpleStringCrypt.Crypt(returnVal.ToString()));

                if (viewControllerBase.Request.Cookies.AllKeys.Contains(key))
                {
                    viewControllerBase.Response.Cookies.Set(cookie);
                }
                else
                {
                    viewControllerBase.Response.Cookies.Add(cookie);
                }
            }
            return ((type)returnVal);
        }

    }
}
